﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace Silverlight.InputCtrl
{
    /// <summary>
    /// MaskEdit Control
    /// </summary>
    /// <remarks>
    /// Input data is validated according to the mask set
    /// </remarks>
    public class MaskedEdit : TextBox
    {

        #region Private Variables

        /// <summary>
        /// class to persist the preview and text selection
        /// </summary>
        private class TextPreview
        {
            public int SelectionStart { get; set; }
            public int SelectionLength { get; set; }
            public string Text { get; set; }
        }

        /// <summary>
        /// Patterns List with valid char from mask
        /// </summary>
        /// <remarks>
        ///  9 = only numeric
        ///  A = only letter 
        ///  C = only Custom - match with property FilterText
        ///  Z = Numeric + Custom
        ///  # = Letter + Custom
        ///  X = any digit 
        /// </remarks>
        private const string _ValidChar = @"9ACZ#X";

        /// <summary>
        /// Enum for define Data Type input
        /// </summary>
        private enum InputDataType
        {
            None,
            Repeater,
            Number,
            DateY2,
            DateY4,
            TimeHM,
            TimeHMS
        }

        /// <summary>
        ///  Predefined Mask Data type.
        ///  Symbols and placeholders will replaced with cultureInfo 
        /// </summary>
        /// <remarks>
        ///  NUMBER => RightNumber([$S]???.???[$S|S%]) = optional Money and/ou signal + Number with ??? (before point) integer position and ??? (after point) digits decimal
        ///  NUMBER => LeftNumber([$S]???.???[$S|S%]) = optional Money and/ou signal + Number with ??? (before point) integer position and ??? (after point) digits decimal
        ///  DATEY2 => ShortDate = 99/99/99 
        ///  DATEY4 => LongDate = 99/99/9999
        ///  TIMEHM => ShortTime = 99:99
        ///  TIMEHMS=> LongTime = 99:99:99
        ///  TIMEHM => ShortTimeAMPM = 99:99*TT
        ///  TIMEHMS=> LongTimeAMPM = 99:99:99*TT
        ///  CUSTOM => R{P}([U|L]???) = Repeater {P} ??? times. Optional [U|L] :  U= Uppercase or L=Lowercase.
        /// </remarks>
        private InputDataType _DataType = InputDataType.None;
        

        /// <summary>
        /// Default Culture to display Data
        /// </summary>
        private CultureInfo _CultureInfoDisplay = System.Threading.Thread.CurrentThread.CurrentCulture;

        /// <summary>
        /// Default Culture to Load Data
        /// </summary>
        private CultureInfo _CultureInfoLoad = System.Threading.Thread.CurrentThread.CurrentCulture;

        
        /// <summary>
        /// Mask Escape char
        /// </summary>
        private const char _EscapeChar = '\\';

        /// <summary>
        /// MOdify to Upper Lower Case
        /// mask must start @ + modify Char
        /// </summary>
        private const string _ValidModifyChar = @"UL";

        /// <summary>
        /// Signal Mask
        /// </summary>
        private const char _ValidSignalChar = 'S';

        /// <summary>
        /// AM/PM Mask
        /// </summary>
        private const char _ValidAMPMChar = 'T';

        
        /// <summary>
        /// List with special char from mask.
        /// at runtime replace with culture property.
        /// </summary>
        /// <remarks>
        ///  / = Date placeholder
        ///  : = Time placeholder
        ///  . = Decimal placeholder
        ///  $ = Money Symbol
        ///  * = Space 
        ///  % = Porcent Symbol
        ///  , = Thousands placeholder
        /// </remarks>
        private const string _SpecialChar = @"$*%,/:.";

        /// <summary>
        /// Flag Transform Input to Uppercase
        /// </summary>
        private bool _InputToUpper = false;

        /// <summary>
        /// Flag Transform input to Lowercase
        /// </summary>
        private bool _InputToLower = false;

        /// <summary>
        /// Flag Show Sign When press +/- in any position
        /// </summary>
        private bool _ShowSignal = false;

        /// <summary>
        /// Flag Show AM/PM When press First letter of symbol in any position
        /// </summary>
        private bool _ShowAMPM = false;

        /// <summary>
        /// Original Background Color
        /// </summary>
        private Brush _NormalBackground = null;

        /// <summary>
        /// Original Foreground Color
        /// </summary>
        private Brush _NormalForeground = null;
        
        /// <summary>
        /// Current Cursor position in textbox
        /// </summary>
        private int _CursorPosition = -1;

        /// <summary>
        /// Formated Mask to display 
        /// </summary>
        private string _MaskFormated = "";

        /// <summary>
        /// Last InputMask
        /// </summary>
        private StringBuilder _LastTextMask = null;

        /// <summary>
        /// Internal Mask to control type input data
        /// </summary>
        /// <remarks>
        /// char 0 = empty user input position
        /// char 1 = delimit position
        /// char 2 = escape value
        /// char 3 = not empty user input position
        /// char 4 = signal Position or AMPM Position
        /// char 5 = Symbol Position
        /// </remarks>
        private char[] _MaskInternalType = null;

        /// <summary>
        /// Mask to capture charMask Position
        /// </summary>
        /// <remarks>
        ///  0 = no user input position
        ///  9 = only numeric
        ///  A = only letter 
        ///  C = only Custom - match with property FilterText
        ///  Z = Numeric + Custom
        ///  J = Letter + Custom
        ///  X = any digit 
        /// </remarks>
        private char[] _MaskInputChar = null;

        /// <summary>
        /// Mask with char Delimetes
        /// </summary>
        /// <remarks>
        private char[] _MaskTemplate = null;

        /// <summary>
        /// String Mask to Apply
        /// </summary>
        private string _MaskToApply = "";

        /// <summary>
        /// Fist Valid input Position
        /// </summary>
        private int _InputFirstPos = -1;

        /// <summary>
        /// Last Valid input Position
        /// </summary>
        private int _InputLastPos = -1;

        /// <summary>
        /// Flag indicator has decimal in Mask
        /// </summary>
        private bool _HasDecimalMask = false;

        /// <summary>
        /// Flag indicator has Date separator in Mask
        /// </summary>
        private bool _HasDateSepMask = false;

        /// <summary>
        /// Flag indicator has Time separator in Mask
        /// </summary>
        private bool _HasTimeSepMask = false;

        /// <summary>
        /// Flag Valid Keypress to input position
        /// </summary>
        private bool _keyPreviewValid = false;

        /// <summary>
        /// Flag Input Data input is Unknown
        /// </summary>
        private bool _keyPreviewUnknown = false;

        /// <summary>
        /// Flag behavior to Shift left input when press delete
        /// </summary>
        private bool _ShiftLeftOnDelete = false;

        /// <summary>
        /// Flag behavior Shift Right input when press delete
        /// </summary>
        private bool _Rightbehavior = false;

        /// <summary>
        /// Flag This control is loaded
        /// </summary>
        private bool _Loaded = false;

        /// <summary>
        /// Saved Preview Mask and Select Text
        /// </summary>
        private TextPreview _SavedPreview = null;

        /// <summary>
        /// Fixer Cursor position when Right Direction
        /// </summary>
        private int _DefaultRightCursorPos = 0;

        /// <summary>
        /// Flag LostFocus Executed
        /// </summary>
        private bool _IsLostFocus = true;

        /// <summary>
        /// Flag Detect First Press
        /// </summary>
        private bool _IsFirstPress = false;

        #endregion

        #region Constructor

        /// <summary>
        /// Constructor
        /// </summary>
        public MaskedEdit()
            : base()
        {
            base.Loaded += new RoutedEventHandler(MaskEdit_Loaded);
        }

        #endregion

        #region private Events

        private bool _NotChanged = false;
        private void MaskEdit_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (_NotChanged)
            {
                _NotChanged = false;
                return;
            } 
            if (Common.IsInDesignMode)
            {
                ResolvePartternMask();
                if (_MaskToApply == base.Text)
                {
                    return;
                }
                else
                {
                    base.Text = _MaskToApply;
                }
            }
            if (!_Loaded || _IsLostFocus)
            {
                return;
            }
            if (_LastTextMask.ToString() == base.Text || !_keyPreviewValid)
            {
                if (base.MaxLength != _MaskFormated.Length)
                {
                    base.MaxLength = _MaskFormated.Length;
                }
                return;
            }
            char MaskKey = (char)0; ;
            string PreviewInput = "";
            int RightCursor = _DefaultRightCursorPos;
            int LeftCursor = _InputFirstPos;
            if (_Rightbehavior && FixedCursorRightPosition)
            {
                int? aux = GetRightNextEmptyPosition();
                if (aux.HasValue)
                {
                    MaskKey = _MaskInputChar[aux.Value];
                }
                PreviewInput = base.Text.Substring(_CursorPosition, 1);
            }
            else if (_Rightbehavior && _CursorPosition == _DefaultRightCursorPos)
            {
                int? aux = GetRightNextEmptyPosition();
                if (aux.HasValue)
                {
                    MaskKey = _MaskInputChar[aux.Value];
                }
                PreviewInput = base.Text.Substring(_CursorPosition, 1);
            }
            else
            {
                MaskKey = _MaskInputChar[_CursorPosition];
                PreviewInput = base.Text.Substring(_CursorPosition, 1);
            }
            if (_InputToLower)
            {
                PreviewInput = PreviewInput.ToLower();
            }
            else if (_InputToUpper)
            {
                PreviewInput = PreviewInput.ToUpper();
            }
            if (_SavedPreview != null)
            {
                // has previus selected text
                // First Clear saved Preview
                // next insert Keypress

                // Cleaning saved preview
                base.Text = _SavedPreview.Text;
                base.Select(_SavedPreview.SelectionStart, _SavedPreview.SelectionLength);
                base.SelectionStart = _SavedPreview.SelectionStart;
                _SavedPreview = null;
                ClearValueToMask();
                base.Select(_CursorPosition, 0);
                if (_ShiftLeftOnDelete)
                {
                    ShiftLeft(_CursorPosition);
                    base.Select(_CursorPosition, 0);
                }
                // inserting Preview input
                string aux = base.Text.Substring(0, _CursorPosition);
                aux += PreviewInput;
                aux += base.Text.Substring(_CursorPosition);
                base.Text = aux;
                base.Select(_CursorPosition, 0);
            }
            if (_keyPreviewUnknown)
            {
                bool isNegativeSignal = KeyHelper.IsNegativeSignal(PreviewInput, _CultureInfoDisplay);
                bool isPositiveSignal = KeyHelper.IsPositiveSignal(PreviewInput, _CultureInfoDisplay);
                bool IsDecimalPlacehold = KeyHelper.IsDecimalPlacehoder(PreviewInput, _CultureInfoDisplay);
                bool IsDatePlacehold = KeyHelper.IsDatePlaceholder(PreviewInput, _CultureInfoDisplay);
                bool IsTimePlacehold = KeyHelper.IsTimePlaceholder(PreviewInput, _CultureInfoDisplay);
                bool IsAMPlacehold = KeyHelper.IsAMSignal(PreviewInput, _CultureInfoDisplay);
                bool IsPMPlacehold = KeyHelper.IsPMSignal(PreviewInput, _CultureInfoDisplay);
                bool keyPreviewFound = false;
                if (isPositiveSignal || isNegativeSignal)
                {
                    keyPreviewFound = true;
                    if (isNegativeSignal)
                    {
                        if (NegativeBackground != null)
                        {
                            base.Background = NegativeBackground;
                        }
                        if (NegativeForeground != null)
                        {
                            base.Foreground = NegativeForeground;
                        }
                    }
                    else if (isPositiveSignal)
                    {
                        base.Background = _NormalBackground;
                        base.Foreground = _NormalForeground;
                    }
                    base.Text = _LastTextMask.ToString();
                    base.Select(_CursorPosition, 0);
                    char[] charText = base.Text.ToCharArray();
                    int[] signals = GetSignalPosition();
                    foreach (var item in signals)
                    {
                        if (isNegativeSignal)
                        {
                            charText[item] = CultureHelper.GetNegativeSignal(_CultureInfoDisplay).ToCharArray()[0];
                        }
                        else if (isPositiveSignal)
                        {
                            charText[item] = CultureHelper.GetPositiveSignal(_CultureInfoDisplay).ToCharArray()[0];
                        }
                    }
                    StringBuilder result = new StringBuilder();
                    foreach (var item in charText)
                    {
                        result.Append(item);
                    }
                    base.Text = result.ToString();
                }
                else if (IsAMPlacehold || IsPMPlacehold)
                {
                    keyPreviewFound = true;
                    base.Text = _LastTextMask.ToString();
                    base.Select(_CursorPosition, 0);
                    char[] charText = base.Text.ToCharArray();
                    int? AMPMpos = GetAMPMPosition();
                    if (AMPMpos.HasValue)
                    {
                        string s = "";
                        if (IsAMPlacehold)
                        {
                            s = CultureHelper.GetAMplaceholder(_CultureInfoDisplay).Substring(0, 1);
                        }
                        else
                        {
                            s = CultureHelper.GetPMplaceholder(_CultureInfoDisplay).Substring(0, 1);
                        }
                        charText[AMPMpos.Value] = s.ToCharArray()[0];
                    }
                    StringBuilder result = new StringBuilder();
                    foreach (var item in charText)
                    {
                        result.Append(item);
                    }
                    base.Text = result.ToString();
                }
                else if (IsDecimalPlacehold && !FixedCursorRightPosition)
                {
                    keyPreviewFound = true;
                    base.Text = _LastTextMask.ToString();
                    base.Select(_CursorPosition, 0);
                    int PosDec = GetDecimalPosition().Value;
                    if (_Rightbehavior)
                    {
                        if (_CursorPosition == _DefaultRightCursorPos)
                        {
                            PosDec = NextInputPosition(PosDec);
                        }
                    }
                    else
                    {
                        PosDec = NextInputPosition(PosDec);
                    }
                    base.Select(PosDec, 0);
                    _CursorPosition = PosDec;
                }
                else if (IsDatePlacehold && !FixedCursorRightPosition)
                {
                    keyPreviewFound = true;
                    base.Text = _LastTextMask.ToString();
                    base.Select(_CursorPosition, 0);
                    int[] PosDatsep = GetDatePlacehoderPosition();
                    int pcur = -1;
                    foreach (var item in PosDatsep)
                    {
                        if (item > _CursorPosition)
                        {
                            pcur = NextInputPosition(item);
                            break;
                        }
                    }
                    if (pcur == -1 && PosDatsep.Length > 0)
                    {
                        pcur = NextInputPosition(0);
                    }
                    if (pcur != -1)
                    {
                        base.Select(pcur, 0);
                        _CursorPosition = pcur;
                    }
                }
                else if (IsTimePlacehold && !FixedCursorRightPosition)
                {
                    keyPreviewFound = true;
                    base.Text = _LastTextMask.ToString();
                    base.Select(_CursorPosition, 0);
                    int[] PosTmsep = GetTimePosition();
                    int pcur = -1;
                    foreach (var item in PosTmsep)
                    {
                        if (item > _CursorPosition)
                        {
                            pcur = NextInputPosition(item);
                            break;
                        }
                    }
                    if (pcur == -1 && PosTmsep.Length > 0)
                    {
                        pcur = NextInputPosition(0);
                    }
                    if (pcur != -1)
                    {
                        base.Select(pcur, 0);
                        _CursorPosition = pcur;
                    }
                }
                if (!keyPreviewFound)
                {
                    base.Text = _LastTextMask.ToString();
                    base.Select(_CursorPosition, 0);
                }
                else
                {
                    _LastTextMask = new StringBuilder(base.Text);
                    base.Select(_CursorPosition, 0);
                }
            }
            else
            {
                if (!KeyHelper.IsValidKeyAtPos(MaskKey, PreviewInput, FilterText))
                {
                    base.Text = _LastTextMask.ToString();
                    base.Select(_CursorPosition, 0);
                }
                else
                {
                    if (_Rightbehavior && _CursorPosition == _DefaultRightCursorPos)
                    {
                        base.Text = _LastTextMask.ToString();
                        RightCursor = GetRightNextEmptyPosition().Value;
                        ShiftLeftContent(RightCursor);
                        _MaskInternalType[_DefaultRightCursorPos - 1] = (char)3;
                        string aux = base.Text.Substring(0, _DefaultRightCursorPos - 1);
                        aux += PreviewInput;
                        aux += base.Text.Substring(_DefaultRightCursorPos);
                        base.Text = aux;
                        _CursorPosition = _DefaultRightCursorPos;
                        base.Select(_CursorPosition, 0);
                        _LastTextMask = new StringBuilder(base.Text);
                    }
                    else
                    {
                        _MaskInternalType[_CursorPosition] = (char)3;
                        string aux = base.Text.Substring(0, _CursorPosition);
                        aux += PreviewInput;
                        aux += base.Text.Substring(_CursorPosition + 2);
                        base.Text = aux;
                        _CursorPosition = NextInputPosition(_CursorPosition + 1);
                        base.Select(_CursorPosition, 0);
                        _LastTextMask = new StringBuilder(base.Text);
                    }
                }
            }
            base.MaxLength = _MaskFormated.Length;
        }

        private void MaskEdit_SelectionChanged(object sender, RoutedEventArgs e)
        {
            if (Common.IsInDesignMode)
            {
                return;
            }
            if (_IsLostFocus)
            {
                return;
            }
            if (_CursorPosition == base.SelectionStart)
            {
                return;
            }
            _CursorPosition = base.SelectionStart;
            //check Ranger
            if (base.SelectionStart > _InputLastPos + 1)
            {
                _CursorPosition = _InputLastPos + 1;
            }
            else if (base.SelectionStart < _InputFirstPos)
            {
                _CursorPosition = _InputFirstPos;
            }
            //adjust to behavior Rightfixed 
            if (_Rightbehavior && FixedCursorRightPosition)
            {
                _CursorPosition = _InputLastPos + 1;
                base.Select(_CursorPosition, 0);
            }
            else if (_Rightbehavior)
            {
                if (base.SelectionStart < _DefaultRightCursorPos)
                {
                    if (base.SelectionLength == 0 || !_IsFirstPress )
                    {
                        _CursorPosition = _DefaultRightCursorPos;
                        base.Select(_CursorPosition, 0);
                    }
                }
            }
        }

        private void MaskEdit_Loaded(object sender, RoutedEventArgs e)
        {

            base.AcceptsReturn = false;

            if (Common.IsInDesignMode)
            {
                _Loaded = true;
                return;
            }

            _NormalBackground = base.Background;
            _NormalForeground = base.Foreground;

            if (CultureInput != "")
            {
                _CultureInfoDisplay = new CultureInfo(CultureInput);
            }
            if (CultureLoad != "")
            {
                _CultureInfoLoad = new CultureInfo(CultureLoad);
            }


            _DataType =  ResolvePartternMask();
            if (_DataType == InputDataType.None)
            {
                if (!IsValidUserMask()) throw new Exception(Resource.MaskEdit_MaskInvalid);

                if (!_MaskToApply.EndsWith("*"))
                {
                    _MaskToApply += "*";
                }
            }
            
            InitTextMask();

            InternalLoadText();

            base.SelectionChanged += new RoutedEventHandler(MaskEdit_SelectionChanged);
            base.TextChanged += new TextChangedEventHandler(MaskEdit_TextChanged);
            base.GotFocus += new RoutedEventHandler(MaskedEdit_GotFocus);
            base.LostFocus += new RoutedEventHandler(MaskedEdit_LostFocus);
            base.LayoutUpdated += new EventHandler(MaskedEdit_LayoutUpdated);
            _LastTextMask = new StringBuilder(base.Text);
            _Loaded = true;
        }

        void MaskedEdit_LayoutUpdated(object sender, EventArgs e)
        {
            //check two way when control is next focus
            if (UnMaskText() != UnMaskText(_LastTextMask.ToString()))
            {
                // is two way
                _NotChanged = true;
                LoadText(base.Text, _CultureInfoLoad);
            }
            else if (base.Text.Length != _MaskFormated.Length)
            {
                // is two way
                _NotChanged = true;
                LoadText(base.Text, _CultureInfoLoad);
            }
        }

        private void MaskedEdit_LostFocus(object sender, RoutedEventArgs e)
        {
            if (Common.IsInDesignMode)
            {
                return;
            }
            _NotChanged = true;
            string lasttext = base.Text;
            if (ReplaceEmptyNumeric != "")
            {
                int pos = _InputFirstPos;
                char[] input = lasttext.ToCharArray();
                bool hasvalue = false;
                List<int> ReplPos = new List<int>();
                while (pos <= _InputLastPos)
                {
                    if (_MaskInternalType[pos] == (char)0)
                    {
                        if (_MaskInputChar[pos] == '9')
                        {
                            ReplPos.Add(pos);
                            input[pos] = ReplaceEmptyNumeric.ToCharArray()[0];
                        }
                    }
                    else if (_MaskInternalType[pos] == (char)3)
                    {
                        hasvalue = true;
                    }
                    pos++;
                }
                if (hasvalue)
                {
                    foreach (var item in ReplPos)
                    {
                        _MaskInternalType[item] = (char)3;
                    }
                    StringBuilder aux = new StringBuilder();
                    foreach (var item in input)
                    {
                        aux.Append(item);
                    }
                    lasttext = aux.ToString();
                    base.Text = lasttext;
                }
            }
            if (ReplaceEmptyText != "")
            {
                int pos = _InputFirstPos;
                char[] input = lasttext.ToCharArray();
                bool hasvalue = false;
                List<int> ReplPos = new List<int>();
                while (pos <= _InputLastPos)
                {
                    if (_MaskInternalType[pos] == (char)0)
                    {
                        if (_MaskInputChar[pos] == 'X')
                        {
                            ReplPos.Add(pos);
                            input[pos] = ReplaceEmptyText.ToCharArray()[0];
                        }
                    }
                    else if (_MaskInternalType[pos] == (char)3)
                    {
                        hasvalue = true;
                    }
                    pos++;
                }
                if (hasvalue)
                {
                    foreach (var item in ReplPos)
                    {
                        _MaskInternalType[item] = (char)3;
                    }
                    StringBuilder aux = new StringBuilder();
                    foreach (var item in input)
                    {
                        aux.Append(item);
                    }
                    lasttext = aux.ToString();
                    base.Text = lasttext;
                }
            }
            if (_Rightbehavior)
            {
                int? inipos = null;
                if (_HasDecimalMask)
                {
                    inipos = GetDecimalPosition();
                    _CursorPosition = PreviusInputPosition(inipos.Value);
                }
                if (!inipos.HasValue || FixedCursorRightPosition)
                {
                    _CursorPosition = _InputLastPos+1;
                }
            }
            else
            {
                _CursorPosition = _InputFirstPos;
            }
            base.Select(_CursorPosition, 0);
            _IsLostFocus = true;
            _IsFirstPress = false;
            //force layoutupdate - workarroud two way
            string TextAux = base.Text;
            base.Text = TextUnMasked;
            if (!UnMaskedAtLostfocus)
            {
                base.Text = TextAux;
            }
        }

        private void MaskedEdit_GotFocus(object sender, RoutedEventArgs e)
        {
            if (Common.IsInDesignMode)
            {
                return;
            }
            if (UnMaskedAtLostfocus)
            {
                _NotChanged = true;
                LoadText(base.Text, _CultureInfoLoad);
            }
            else
            {
                //check two way when control is next focus
                if (UnMaskText() != UnMaskText(_LastTextMask.ToString()))
                {
                    // is two way
                    _NotChanged = true;
                    LoadText(base.Text, _CultureInfoLoad);
                }
                else if (base.Text.Length != _MaskFormated.Length)
                {
                    // is two way
                    _NotChanged = true;
                    LoadText(base.Text, _CultureInfoLoad);
                }
            }
            if (_Rightbehavior)
            {
                int? inipos = null;
                if (_HasDecimalMask)
                {
                    inipos = GetDecimalPosition();
                    _CursorPosition = inipos.Value;
                }
                if (!inipos.HasValue || FixedCursorRightPosition)
                {
                    _CursorPosition = _InputLastPos+1;
                }
            }
            else
            {
                if (base.SelectionStart < _InputFirstPos)
                {
                    _CursorPosition = _InputFirstPos;
                }
                else if (base.SelectionStart > _InputLastPos)
                {
                    _CursorPosition = _InputLastPos + 1;
                }
                else
                {
                    _CursorPosition = base.SelectionStart;
                }
            }
            base.Select(_CursorPosition, 0);
            _LastTextMask = new StringBuilder(base.Text);
            _IsLostFocus = false;
        }

        #endregion

        #region Overriders

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (!_Loaded)
            {
                return;
            }
            _IsFirstPress = true;
            if (Common.IsInDesignMode)
            {
                base.OnKeyDown(e);
                return;
            }
            _keyPreviewValid = false;
            _keyPreviewUnknown = false;
            base.MaxLength = this._MaskInternalType.Length;
            bool ShiftPress = ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift);
            bool CtrlPress = ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control);
            bool DelPress = (e.Key == Key.Delete);
            bool BackSpacePress = (e.Key == Key.Back);

            if (DelPress || BackSpacePress)
            {
                #region Delete or BackSpacePress
                if (_Rightbehavior && _CursorPosition == _DefaultRightCursorPos)
                {
                    if (base.SelectionLength > 0)
                    {
                        base.Select(_CursorPosition + 1, base.SelectionLength - 1);
                        ClearValueToMask();
                        if (BackSpacePress)
                        {
                            ShiftRight();
                        }
                    }
                    else
                    {
                        ShiftRight();
                    }
                    base.Select(_DefaultRightCursorPos, 0);
                }
                else
                {
                    if (base.SelectionLength != 0)
                    {
                        ClearValueToMask();
                        if (DelPress)
                        {
                            if (_Rightbehavior && _CursorPosition < _DefaultRightCursorPos)
                            {
                                _CursorPosition = _DefaultRightCursorPos;
                                base.Select(_CursorPosition, 0);
                            }
                            else
                            {
                                base.Select(_CursorPosition, 0);
                                if (_ShiftLeftOnDelete)
                                {
                                    ShiftLeft(_CursorPosition);
                                    base.Select(_CursorPosition, 0);
                                }
                            }
                        }
                        else //backspace
                        {
                            if (_CursorPosition > _InputFirstPos)
                            {
                                _CursorPosition--;
                                _CursorPosition = PreviusInputPosition(_CursorPosition);
                            }
                            base.Select(_CursorPosition, 0);
                        }
                    }
                    else
                    {
                        if (DelPress)
                        {
                            base.Select(_CursorPosition, 1);
                            ClearValueToMask();
                            base.Select(_CursorPosition, 0);
                            if (_ShiftLeftOnDelete)
                            {
                                ShiftLeft(_CursorPosition);
                                base.Select(_CursorPosition, 0);
                            }
                        }
                        else //backspace
                        {
                            if (_CursorPosition > _InputFirstPos)
                            {
                                _CursorPosition = PreviusInputPosition(_CursorPosition - 1);
                                base.Select(_CursorPosition, 1);
                                ClearValueToMask();
                            }
                            base.Select(_CursorPosition, 0);
                        }
                    }
                }
                e.Handled = true;
                _LastTextMask = new StringBuilder(base.Text);
                #endregion
            }
            else  
            {
                if (e.Key == Key.Tab)
                {
                    e.Handled = false;
                }
                else if (KeyHelper.IsClipboadPaste(e.Key))
                {
                    #region Supress clipboard paste

                    e.Handled = true;
                    _LastTextMask = new StringBuilder(base.Text);

                    #endregion
                }
                else if (KeyHelper.IsMoveKey(e.Key))
                {
                    #region Behavior keys Move and select

                    e.Handled = true;
                    if (e.Key == Key.Left)
                    {
                        if (CtrlPress && !ShiftPress)
                        {
                            _CursorPosition = 0;
                            base.Select(_CursorPosition, 0);
                        }
                        else if (CtrlPress && ShiftPress)
                        {
                            int End = _CursorPosition;
                            base.Select(_InputFirstPos, End - _InputFirstPos);
                            _CursorPosition = _InputFirstPos;
                        }
                        else if (ShiftPress)
                        {
                            if (_CursorPosition > _InputFirstPos)
                            {
                                e.Handled = false;
                            }
                        }
                        else if (_CursorPosition > _InputFirstPos)
                        {
                            _CursorPosition = PreviusInputPosition(_CursorPosition - 1);
                            if (_CursorPosition >= _InputFirstPos)
                            {
                                base.Select(_CursorPosition, 0);
                            }
                        }
                    }
                    else if (e.Key == Key.Right)
                    {
                        if (CtrlPress && !ShiftPress)
                        {
                            _CursorPosition = _MaskInternalType.Length - 1;
                            base.Select(_CursorPosition, 0);
                        }
                        else if (CtrlPress && ShiftPress)
                        {
                            int ini = _CursorPosition;
                            base.Select(ini, _InputLastPos - ini + 1);
                            _CursorPosition = _InputLastPos;
                        }
                        else if (ShiftPress)
                        {
                            if (_CursorPosition+base.SelectionLength  <= _InputLastPos)
                            {
                                e.Handled = false;
                            }
                        }
                        else if (_CursorPosition <= _InputLastPos)
                        {
                            _CursorPosition = NextInputPosition(_CursorPosition + 1);
                            if (_CursorPosition > _InputLastPos)
                            {
                                _CursorPosition = _InputLastPos + 1;
                            }
                            base.Select(_CursorPosition, 0);
                        }
                    }
                    else if (e.Key == Key.Home || e.Key == Key.PageUp)
                    {
                        if (CtrlPress && ShiftPress && e.Key == Key.Home)
                        {
                            int dif = _CursorPosition - _InputFirstPos;
                            base.Select(_InputFirstPos, dif);
                        }
                        else
                        {
                            _CursorPosition = _InputFirstPos;
                            base.Select(_CursorPosition, 0);
                        }
                    }
                    else if (e.Key == Key.End || e.Key == Key.PageDown)
                    {
                        if (CtrlPress && ShiftPress && e.Key == Key.End)
                        {
                            int dif = _InputLastPos - _CursorPosition +1;
                            base.Select(_InputFirstPos, dif);
                        }
                        else
                        {
                            _CursorPosition = _InputLastPos + 1;
                            base.Select(_CursorPosition, 0);
                        }
                    }

                    #endregion
                }
                else
                {
                    #region propagate validate input Mask to textchanged 

                    e.Handled = true;

                    if (_ShowSignal)
                    { 
                        if (KeyHelper.IsSignalKeyPreview(e.Key))
                        {
                            _keyPreviewUnknown = true;
                        }
                    }
                    if (_ShowAMPM)
                    {
                        if (KeyHelper.IsAMPMKeyPreview(e.Key,_CultureInfoDisplay))
                        {
                            _keyPreviewUnknown = true;
                        }
                    }
                    if (_HasDecimalMask && !_keyPreviewUnknown)
                    {
                        if (KeyHelper.IsDecimalKeyPreview(e.Key))
                        {
                            _keyPreviewUnknown = true;
                        }
                    }
                    if (_HasDateSepMask && !_keyPreviewUnknown)
                    {
                        if (KeyHelper.IsDateplaceholderKeyPreview(e.Key))
                        {
                            _keyPreviewUnknown = true;
                        }
                    }
                    if (_HasTimeSepMask && !_keyPreviewUnknown)
                    {
                        if (KeyHelper.IsTimeplaceholderKeyPreview(e.Key))
                        {
                            _keyPreviewUnknown = true;
                        }
                    }
                    if (_keyPreviewUnknown)
                    {
                        base.MaxLength++;
                        e.Handled = false;
                        _keyPreviewValid = true;
                    }
                    if ((_Rightbehavior && _CursorPosition == _DefaultRightCursorPos) | (_CursorPosition >= _InputFirstPos && _CursorPosition <= _InputLastPos && !_keyPreviewValid))
                    {
                        _SavedPreview = null;
                        if (_Rightbehavior && _CursorPosition == _DefaultRightCursorPos)
                        {
                            int? NextPos = GetRightNextEmptyPosition();
                            if (NextPos.HasValue)
                            {
                                base.MaxLength++;
                                e.Handled = false;
                                _keyPreviewValid = true;
                            }
                        }
                        else
                        {
                            if (_MaskInputChar[_CursorPosition] != (char)0)
                            {
                                if (base.SelectionLength > 0)
                                {
                                    _SavedPreview = new TextPreview();
                                    _SavedPreview.SelectionLength = base.SelectionLength;
                                    _SavedPreview.SelectionStart = base.SelectionStart;
                                    _SavedPreview.Text = base.Text;
                                }
                                base.MaxLength++;
                                e.Handled = false;
                                _keyPreviewValid = true;
                            }
                        }
                    }

                    #endregion
                }
            }
            base.OnKeyDown(e);
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// convert data input to mask input formated
        /// </summary>
        public void LoadText(object value)
        {
            LoadText(value, _CultureInfoLoad);
        }

        public void Reload()
        {
            if (!_Loaded) return;
            _Loaded = false;
            base.AcceptsReturn = false;
            if (Common.IsInDesignMode)
            {
                _Loaded = true;
                return;
            }
            base.SelectionChanged -= MaskEdit_SelectionChanged;
            base.TextChanged -= MaskEdit_TextChanged;
            base.GotFocus -= MaskedEdit_GotFocus;
            base.LostFocus -= MaskedEdit_LostFocus;
            base.LayoutUpdated -= MaskedEdit_LayoutUpdated;

            InitTextMask();
            InternalLoadText();

            base.SelectionChanged += new RoutedEventHandler(MaskEdit_SelectionChanged);
            base.TextChanged += new TextChangedEventHandler(MaskEdit_TextChanged);
            base.GotFocus += new RoutedEventHandler(MaskedEdit_GotFocus);
            base.LostFocus += new RoutedEventHandler(MaskedEdit_LostFocus);
            base.LayoutUpdated += new EventHandler(MaskedEdit_LayoutUpdated);
            _LastTextMask = new StringBuilder(base.Text);
            _Loaded = true;
        }

        private string FormatDataInputToDate(object value, CultureInfo CultureLoad)
        {
            DateTime dtaux;
            if (!DateTime.TryParse(value.ToString(), CultureLoad, DateTimeStyles.AssumeLocal, out dtaux))
            { 
                return value.ToString();
            }
            string cultmk = CultureLoad.DateTimeFormat.ShortDatePattern;
            string sep = CultureHelper.GetDateplaceholder(CultureLoad);
            string[] cultspt = cultmk.Split(sep.ToCharArray());
            cultmk = "";
            foreach (var item in cultspt)
            {
                if (item.Length > 2)
                {
                    if (_DataType == InputDataType.DateY2)
                    {
                        cultmk += item.Substring(0, 2) + sep;
                    }
                    else
                    {
                        cultmk += item + sep;
                    }
                }
                else
                {
                    cultmk += item + sep;
                }
            }
            if (cultmk.EndsWith(sep))
            {
                cultmk = cultmk.Substring(0, cultmk.Length - 1);
            }
            return dtaux.ToString(cultmk);
        }

        private string FormatDataInputToTime(object value, CultureInfo CultureLoad)
        {
            TimeSpan ts = new TimeSpan();
            if (!TimeSpan.TryParse(value.ToString(), out ts))
            {
                return value.ToString();
            }
            string sep = CultureHelper.GetTimeplaceholder(CultureLoad);
            if (_DataType == InputDataType.TimeHM)
            {
                return ts.Hours.ToString().PadLeft(2, '0') + sep + ts.Minutes.ToString().PadLeft(2, '0');
            }
            return ts.Hours.ToString().PadLeft(2, '0') + sep + ts.Minutes.ToString().PadLeft(2, '0') + sep + ts.Seconds.ToString().PadLeft(2, '0');
        }
        
        public void LoadText(object value, CultureInfo CultureLoad)
        {

            string DataInput = "";
            bool IsPM = false;

            #region Convert object to string

            if (value is DateTime)
            {
                if (_DataType == InputDataType.DateY2 || _DataType == InputDataType.DateY4)
                {
                    DataInput = FormatDataInputToDate(value,CultureLoad);
                }
                else
                {
                    DataInput = System.Convert.ToString(value, CultureLoad);
                }
            }
            else if (value is TimeSpan)
            {
                if (_DataType == InputDataType.TimeHM || _DataType == InputDataType.TimeHMS)
                {
                    DataInput = FormatDataInputToTime(value, CultureLoad);
                    if (_ShowAMPM)
                    {
                        int newvalue = 0;
                        if (Int32.TryParse(DataInput.Substring(0,2),out newvalue))
                        {
                            if (newvalue > 12)
                            {
                                newvalue -= 12;
                                DataInput = newvalue.ToString().PadLeft(2, '0') + DataInput.Substring(2);
                                IsPM = true;
                            }
                        }
                    }
                }
                else
                {
                    DataInput = System.Convert.ToString(value, CultureLoad);
                }
            }
            else if (value is Int16 || value is Int32 || value is Int64 || value is Decimal || value is float || value is Double)
            {
                DataInput = Double.Parse(DataInput, NumberStyles.Number,CultureLoad).ToString();
            }
            else if (value is string && value.ToString().Length !=0)
            {
                switch (_DataType)
                {
                    case InputDataType.None:
                    case InputDataType.Repeater:
                        DataInput = System.Convert.ToString(value, CultureLoad);
                        break;
                    case InputDataType.Number:
                        {
                            double d = 0;
                            if (double.TryParse(System.Convert.ToString(value, CultureLoad), NumberStyles.Number,CultureLoad, out d))
                            {
                                DataInput = d.ToString();
                            }
                        }
                        break;
                    case InputDataType.DateY2:
                    case InputDataType.DateY4:
                        DataInput = FormatDataInputToDate(value, CultureLoad);
                        break;
                    case InputDataType.TimeHM:
                    case InputDataType.TimeHMS:
                        {
                            string AUX = value.ToString().ToUpper();
                            string[] ampm = CultureHelper.GetAMPMplaceholders(CultureLoad);
                            if (_ShowAMPM)
                            {
                                if (AUX.EndsWith(ampm[0].ToUpper()))
                                {
                                    AUX = AUX.Replace(ampm[0].ToUpper(), "");
                                }
                                else if (AUX.EndsWith(ampm[1].ToUpper()))
                                {
                                    AUX = AUX.Replace(ampm[1].ToUpper(), "");
                                    IsPM = true;
                                }
                                AUX = AUX.Trim();
                            }
                            DataInput = FormatDataInputToTime(AUX, CultureLoad);
                            if (_ShowAMPM)
                            {
                                int newvalue = 0;
                                if (Int32.TryParse(DataInput.Substring(0, 2), out newvalue))
                                {
                                    if (newvalue > 12 && newvalue <= 23)
                                    {
                                        newvalue -= 12;
                                        DataInput = newvalue.ToString().PadLeft(2, '0') + DataInput.Substring(2);
                                        IsPM = true;
                                    }
                                }
                            }
                        }
                        break;
                }
            }
            else
            {
                DataInput = System.Convert.ToString(value, CultureLoad);
            }

            #endregion

            base.Text = _MaskFormated;
            _LastTextMask = new StringBuilder(base.Text);
            
            
            /// Clear internal Control Empty
            for (int i = 0; i < _MaskInternalType.Length; i++)
            {
                if (_MaskInternalType[i] == (char)3)
                {
                    _MaskInternalType[i] = (char)0;
                }
            }
            /// char 0 = empty user input position
            /// char 1 = delimit position
            /// char 2 = escape value
            /// char 3 = not empty user input position
            /// char 4 = signal Position
            /// char 5 = Symbol Position

            if (DataInput.Length != 0)
            {
                if (_InputToLower)
                {
                    DataInput = DataInput.ToLower();
                }
                if (_InputToUpper)
                {
                    DataInput = DataInput.ToUpper();
                }
                char[] loadinput = null;
                char[] result = _MaskFormated.ToCharArray();
                char[] USMask = _MaskToApply.ToCharArray();
                if (_DataType == InputDataType.Number)
                {
                    #region Load Data to format number

                    bool IsNegative = false;
                    if (DataInput.StartsWith(CultureHelper.GetNegativeSignal(CultureLoad)))
                    {
                        DataInput = DataInput.Substring(1);
                        IsNegative = true;
                    }
                    else if (DataInput.StartsWith(CultureHelper.GetPositiveSignal(CultureLoad)))
                    {
                        DataInput = DataInput.Substring(1);
                    }

                    if (!_Rightbehavior)
                    {
                        #region Left to Right

                        char dec = CultureHelper.GetDecimalplaceholder(CultureLoad).ToCharArray()[0];
                        string[] partinput = DataInput.Split(dec);

                        //integer part
                        loadinput = partinput[0].ToCharArray();
                        int PosInput = 0;
                        int PosMask = this.GetLeftNextEmptyPosition().Value;
                        while (PosInput < loadinput.Length)
                        {
                            if (Char.IsNumber(loadinput[PosInput]))
                            {
                                if (_MaskInternalType[PosMask] == (char)0)
                                {
                                    char IMask = _MaskInputChar[PosMask];
                                    if (KeyHelper.IsValidKeyAtPos(IMask, loadinput[PosInput].ToString(), FilterText))
                                    {
                                        result[PosMask] = loadinput[PosInput];
                                        _MaskInternalType[PosMask] = (char)3;
                                    }
                                }
                                PosInput++;
                                int? posnext = this.GetLeftNextEmptyPosition();
                                if (!posnext.HasValue)
                                {
                                    break;
                                }
                                PosMask = posnext.Value;
                            }
                            else
                            {
                                break;
                            }
                        }
                        //part decimal
                        if (partinput.Length > 1 && _HasDecimalMask)
                        {
                            loadinput = partinput[1].ToCharArray();
                            PosInput = 0;
                            PosMask = NextInputPosition(GetDecimalPosition().Value);
                            while (PosInput < loadinput.Length)
                            {
                                if (Char.IsNumber(loadinput[PosInput]))
                                {
                                    if (_MaskInternalType[PosMask] == (char)0)
                                    {
                                        char IMask = _MaskInputChar[PosMask];
                                        if (KeyHelper.IsValidKeyAtPos(IMask, loadinput[PosInput].ToString(), FilterText))
                                        {
                                            result[PosMask] = loadinput[PosInput];
                                            _MaskInternalType[PosMask] = (char)3;
                                        }
                                    }
                                    PosInput++;
                                    PosMask++;
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }

                        #endregion
                    }
                    else
                    {
                        #region Right to Left 

                        char dec = CultureHelper.GetDecimalplaceholder(CultureLoad).ToCharArray()[0];
                        string[] partinput = DataInput.Split(dec);

                        //integer part
                        loadinput = partinput[0].ToCharArray().Reverse().ToArray();
                        int PosInput = 0;
                        int PosMask = this.GetRightNextEmptyPosition().Value;
                        while (PosInput < loadinput.Length)
                        {
                            if (Char.IsNumber(loadinput[PosInput]))
                            {
                                if (_MaskInternalType[PosMask] == (char)0)
                                {
                                    char IMask = _MaskInputChar[PosMask];
                                    if (KeyHelper.IsValidKeyAtPos(IMask, loadinput[PosInput].ToString(), FilterText))
                                    {
                                        result[PosMask] = loadinput[PosInput];
                                        _MaskInternalType[PosMask] = (char)3;
                                    }
                                }
                                PosInput++;
                                int? posnext  = this.GetRightNextEmptyPosition();
                                if (!posnext.HasValue)
                                {
                                    break;
                                }
                                PosMask = posnext.Value;
                            }
                            else
                            {
                                break;
                            }
                        }
                        //part decimal
                        if (partinput.Length > 1 && _HasDecimalMask)
                        {
                            loadinput = partinput[1].ToCharArray();
                            PosInput = 0;
                            PosMask = NextInputPosition(_DefaultRightCursorPos);
                            while (PosInput < loadinput.Length)
                            {
                                if (Char.IsNumber(loadinput[PosInput]))
                                {
                                    if (_MaskInternalType[PosMask] == (char)0)
                                    {
                                        char IMask = _MaskInputChar[PosMask];
                                        if (KeyHelper.IsValidKeyAtPos(IMask, loadinput[PosInput].ToString(), FilterText))
                                        {
                                            result[PosMask] = loadinput[PosInput];
                                            _MaskInternalType[PosMask] = (char)3;
                                        }
                                    }
                                    PosInput++;
                                    PosMask++;
                                }
                                else 
                                {
                                    break;
                                }
                            }
                        }

                        #endregion
                    }

                    #region Set Negative signal and color

                    if (IsNegative)
                    {
                        int[] signals = GetSignalPosition();
                        foreach (var item in signals)
                        {
                            result[item] = CultureHelper.GetNegativeSignal(CultureLoad).ToCharArray()[0];
                        }
                        if (NegativeBackground != null)
                        {
                            base.Background = NegativeBackground;
                        }
                        if (NegativeForeground != null)
                        {
                            base.Foreground = NegativeForeground;
                        }
                    }
                    else
                    {
                        base.Background = _NormalBackground;
                        base.Foreground = _NormalForeground;
                    }

                    #endregion

                    #endregion
                }
                else if (_DataType == InputDataType.DateY2 || _DataType == InputDataType.DateY4)
                {
                    #region Load dato to format Date

                    loadinput = DataInput.ToCharArray();
                    int PosInput = 0;
                    int PosMask = _InputFirstPos;
                    while (PosInput < loadinput.Length && PosMask <= _InputLastPos)
                    {
                        if (_MaskInternalType[PosMask] == (char)0)
                        {
                            char IMask = _MaskInputChar[PosMask];
                            if (KeyHelper.IsValidKeyAtPos(IMask, loadinput[PosInput].ToString(), FilterText))
                            {
                                result[PosMask] = loadinput[PosInput];
                                _MaskInternalType[PosMask] = (char)3;
                                PosInput++;
                                PosMask++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        else if (_MaskInternalType[PosMask] == (char)1)
                        {
                            if (loadinput[PosInput].ToString() == CultureHelper.GetDateplaceholder(CultureLoad))
                            {
                                PosInput++;
                                PosMask++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }

                    #endregion
                }
                else if (_DataType == InputDataType.TimeHM || _DataType == InputDataType.TimeHMS)
                {
                    #region Load data to format Time

                    loadinput = DataInput.ToCharArray();
                    int PosInput = 0;
                    int PosMask = _InputFirstPos;
                    //bool AmPm = false;
                    while (PosInput < loadinput.Length && PosMask <= _InputLastPos)
                    {
                        if (_MaskInternalType[PosMask] == (char)0)
                        {
                            char IMask = _MaskInputChar[PosMask];
                            if (KeyHelper.IsValidKeyAtPos(IMask, loadinput[PosInput].ToString(), FilterText))
                            {
                                result[PosMask] = loadinput[PosInput];
                                _MaskInternalType[PosMask] = (char)3;
                                PosInput++;
                                PosMask++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        else if (_MaskInternalType[PosMask] == (char)1)
                        {
                            if (loadinput[PosInput].ToString() == CultureHelper.GetTimeplaceholder(CultureLoad))
                            {
                                PosInput++;
                                PosMask++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (_ShowAMPM)
                    {
                        int? AMPMpos = GetAMPMPosition();
                        if (AMPMpos.HasValue)
                        {
                            string s = "";
                            if (!IsPM)
                            {
                                s = CultureHelper.GetAMplaceholder(_CultureInfoDisplay).Substring(0, 1);
                            }
                            else
                            {
                                s = CultureHelper.GetPMplaceholder(_CultureInfoDisplay).Substring(0, 1);
                            }
                            result[AMPMpos.Value] = s.ToCharArray()[0];
                        }
                    }

                    #endregion
                }
                else if (_DataType == InputDataType.None || _DataType == InputDataType.Repeater)
                {
                    #region Load data to repeater / user format

                    loadinput = DataInput.ToCharArray();
                    int PosInput = 0;
                    int PosMask = _InputFirstPos;
                    while (PosInput < loadinput.Length && PosMask <= _InputLastPos)
                    {
                        if (_MaskInternalType[PosMask] == (char)0)
                        {
                            char IMask = _MaskInputChar[PosMask];
                            if (KeyHelper.IsValidKeyAtPos(IMask, loadinput[PosInput].ToString(), FilterText))
                            {
                                result[PosMask] = loadinput[PosInput];
                                _MaskInternalType[PosMask] = (char)3;
                            }
                            PosInput++;
                            int? newpos = this.GetLeftNextEmptyPosition();
                            if (newpos.HasValue)
                            {
                                PosMask = newpos.Value;
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }

                    #endregion
                }
                StringBuilder sb = new StringBuilder();
                sb.Append(result);
                base.Text = sb.ToString();
                _LastTextMask = new StringBuilder(sb.ToString());

            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// convert data input from Databind or xmal to Mask format
        /// </summary>
        private void InternalLoadText()
        {
            LoadText(base.Text,_CultureInfoLoad);
        }

        /// <summary>
        /// Get last not empty Position at (left to right)
        /// </summary>
        private int? GetLastNotEmptyPosition()
        {
            int? result = null;
            int pos = _InputFirstPos;
            while (pos <= _InputLastPos)
            {
                if (_MaskInternalType[pos] == (char)3)
                {
                    result = pos;
                }
                pos++;
            }
            return result;
        }

        /// <summary>
        /// Get next empty Position at left (left to right)
        /// </summary>
        /// <returns>null if not found</returns>
        private int? GetLeftNextEmptyPosition()
        {
            int? result = _InputFirstPos;
            while (_MaskInternalType[result.Value] != (char)0)
            {
                result++;
                if (result > _InputLastPos)
                {
                    result = null;
                    break;
                }
            }
            return result;
        }

        /// <summary>
        /// Get next empty Position at right (right to left)
        /// </summary>
        /// <returns>null if not found</returns>
        private int? GetRightNextEmptyPosition()
        {
            int? result = _DefaultRightCursorPos;
            while (_MaskInternalType[result.Value] != (char)0)
            {
                result--;
                if (result < 0)
                {
                    result = null;
                    break;
                }
            }
            return result;
        }

        /// <summary>
        /// Return array with positions of Signals in mask
        /// </summary>
        /// <returns>int[] with positions signals</returns>
        private int[] GetSignalPosition()
        {
            List<int> result = new List<int>();
            for (int i = 0; i < _MaskInternalType.Length; i++)
            {
                if (_MaskInternalType[i] == (char)4 && _ShowSignal)
                {
                    result.Add(i);
                }
            }
            return result.ToArray();
        }

        /// <summary>
        /// Return position of AMPM in mask
        /// </summary>
        /// <returns>int with positions signals</returns>
        private int? GetAMPMPosition()
        {
            int? result = null;
            for (int i = 0; i < _MaskInternalType.Length; i++)
            {
                if (_MaskInternalType[i] == (char)4 && _ShowAMPM)
                {
                    result = i;
                    break;
                }
            }
            return result;
        }


        /// <summary>
        /// Return array with positions of date placehoder in mask
        /// </summary>
        /// <returns>int[] with positions date placehoder</returns>
        private int[] GetDatePlacehoderPosition()
        {
            List<int> result = new List<int>();
            for (int i = 0; i < _MaskInternalType.Length; i++)
            {
                if (_MaskInternalType[i] == (char)1)
                {
                    if (_MaskTemplate[i] == '/')
                    {
                        result.Add(i);
                    }
                }
            }
            return result.ToArray();
        }

        /// <summary>
        /// Return position of decimal placehoder in mask
        /// </summary>
        /// <returns>null if not found or positions decimal placehoder in mask</returns>
        private int? GetDecimalPosition()
        {
            int? result = null;
            for (int i = 0; i < _MaskInternalType.Length; i++)
            {
                if (_MaskInternalType[i] == (char)1)
                {
                    if (_MaskTemplate[i] == '.')
                    {
                        result = i;
                        break;
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// Return position of decimal placehoder in mask
        /// </summary>
        /// <returns>null if not found or positions decimal placehoder in mask</returns>
        private int[] GetTimePosition()
        {
            List<int> result = new List<int>();
            for (int i = 0; i < _MaskInternalType.Length; i++)
            {
                if (_MaskInternalType[i] == (char)1)
                {
                    if (_MaskTemplate[i] == ':')
                    {
                        result.Add(i);
                    }
                }
            }
            return result.ToArray();
        }

        /// <summary>
        /// Check position cursor is valid
        /// </summary>
        /// <param name="atualPosition">Position Cursor</param>
        /// <returns>true if position is user input</returns>
        private bool IsValidInputPosition(int atualPosition)
        { 
            if (atualPosition >= _InputFirstPos && atualPosition <= (_InputLastPos))
            {
                return (_MaskInternalType[atualPosition] == (char)0 || _MaskInternalType[atualPosition] == (char)3);
            }
            return false;
        }

        /// <summary>
        /// Move Cursor to previus valid position
        /// </summary>
        /// <param name="atualPosition">Position Cursor</param>
        /// <returns></returns>
        private int PreviusInputPosition(int atualPosition)
        {
            int result = atualPosition;
            while (_MaskInternalType[result] != (char)0 && _MaskInternalType[result] != (char)3)
            {
                result--;
                if (result < 0)
                {
                    break;
                }
            }
            return result;
        }

        /// <summary>
        /// Move Cursor to next valid position
        /// </summary>
        /// <param name="atualPosition">Position Cursor</param>
        /// <returns></returns>
        private int NextInputPosition(int atualPosition)
        {
            int result = atualPosition;
            while (_MaskInternalType[result] != (char)0 && _MaskInternalType[result] != (char)3)
            {
                result++;
                if (result > _MaskInternalType.Length-1)
                {
                    break;
                }
            }
            if (result > _InputLastPos)
            {
                result = _InputLastPos + 1;
            }
            return result;
        }

        /// <summary>
        /// Shift Left content
        /// </summary>
        /// <param name="StartPos">Start Position</param>
        private void ShiftLeft(int StartPos)
        {
            char[] Aux = base.Text.ToCharArray();
            StringBuilder Input = new StringBuilder();
            StringBuilder result = new StringBuilder();
            for (int i = StartPos; i < _MaskInternalType.Length; i++)
            {
                if (_MaskInternalType[i] == (char)3)
                {
                    Input.Append(Aux[i]);
                    Aux[i] = PromptCharacter.ToCharArray()[0];
                    _MaskInternalType[i] = (char)0;
                }
            }
            int posshift = StartPos;
            for (int i = 0; i < Input.Length; i++)
            {
                if (_MaskInternalType[posshift] == (char)0)
                {
                    _MaskInternalType[posshift] = (char)3;
                    Aux[posshift] = Input[i];
                }
                else
                {
                    i--;
                }
                posshift++;
            }
            for (int i = 0; i < Aux.Length; i++)
            {
                result.Append(Aux[i]);
            }
            base.Text = result.ToString();
            _LastTextMask = new StringBuilder(base.Text);
        }

        /// <summary>
        /// Shift Left content 
        /// </summary>
        /// <param name="StartPos">Start Position</param>
        private void ShiftLeftContent(int StartPos)
        {
            char[] Aux = base.Text.ToCharArray();
            StringBuilder Input = new StringBuilder();
            StringBuilder result = new StringBuilder();
            for (int i = StartPos; i < _DefaultRightCursorPos; i++)
            {
                if (_MaskInternalType[i] == (char)3)
                {
                    Input.Append(Aux[i]);
                    Aux[i] = PromptCharacter.ToCharArray()[0];
                    _MaskInternalType[i] = (char)0;
                }
            }
            int posshift = StartPos;
            for (int i = 0; i < Input.Length; i++)
            {
                if (_MaskInternalType[posshift] == (char)0)
                {
                    _MaskInternalType[posshift] = (char)3;
                    Aux[posshift] = Input[i];
                }
                else
                {
                    i--;
                }
                posshift++;
            }
            for (int i = 0; i < Aux.Length; i++)
            {
                result.Append(Aux[i]);
            }
            base.Text = result.ToString();
            _LastTextMask = new StringBuilder(base.Text);
        }


        /// <summary>
        /// Shift Right content
        /// </summary>
        private void ShiftRight()
        {
            char[] Aux = base.Text.ToCharArray();
            StringBuilder Input = new StringBuilder();
            StringBuilder result = new StringBuilder();
            for (int i = _InputFirstPos; i < _DefaultRightCursorPos; i++)
            {
                if (_MaskInternalType[i] == (char)3)
                {
                    Input.Append(Aux[i]);
                    Aux[i] = PromptCharacter.ToCharArray()[0];
                    _MaskInternalType[i] = (char)0;
                }
            }
            if (Input.Length > 1)
            {
                Input.Remove(Input.Length-1, 1);
                var inputrev = Input.ToString().ToCharArray().Reverse();
                foreach (var item in inputrev)
                {
                    int pos = GetRightNextEmptyPosition().Value;
                    Aux[pos] = item;
                    _MaskInternalType[pos] = (char)3;
                }
            }
            for (int i = 0; i < Aux.Length; i++)
            {
                result.Append(Aux[i]);
            }
            base.Text = result.ToString();
            _LastTextMask = new StringBuilder(base.Text);
        }

        /// <summary>
        /// Clear content for range text selected
        /// </summary>
        private void ClearValueToMask()
        {
            char[] Aux = base.Text.ToCharArray();
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < _MaskInternalType.Length; i++)
            {
                if (i >= base.SelectionStart && i < (base.SelectionStart + base.SelectionLength))
                {
                    if (_MaskInternalType[i] == (char)3)
                    {
                        _MaskInternalType[i] = (char)0;
                        result.Append(PromptCharacter);
                    }
                    else
                    {
                        result.Append(Aux[i]);
                    }
                }
                else
                {
                    result.Append(Aux[i]);
                }
            }
            base.Text = result.ToString();
            _LastTextMask = new StringBuilder(base.Text);
        }

        /// <summary>
        ///  Create Parttern Mask (convert predefine mask)
        /// </summary>
        private InputDataType ResolvePartternMask()
        {
            //
            ///  NUMBER => RightNumber([$S]???.???[$S|S%]) = optional Money and/ou signal + Number with ??? (before point) integer position and ??? (after point) digits decimal
            ///  NUMBER => LeftNumber([$S]???.???[$S|S%]) = optional Money and/ou signal + Number with ??? (before point) integer position and ??? (after point) digits decimal
            ///  DATE   => ShortDate = 99/99/99 
            ///  DATE   => LongDate = 99/99/9999
            ///  TIME   => ShortTime = 99:99
            ///  TIME   => LongTime = 99:99:99
            ///  TIMEHM => ShortTimeAMPM = 99:99*TT
            ///  TIMEHMS=> LongTimeAMPM = 99:99:99*TT
            ///  CUSTOM => R{P}([U|L]???) = Repeater {P} ??? times. Optional [U|L] :  U= Uppercase or L=Lowercase.
            //
            _MaskToApply = Mask.ToUpper();
            _ShiftLeftOnDelete = false;
            _Rightbehavior = false;

            InputDataType RetResolve = InputDataType.None;

            if (_MaskToApply.StartsWith("RIGHTNUMBER(") || _MaskToApply.StartsWith("LEFTNUMBER("))
            {
                bool Ok = true;
                #region transform RightNumber in mask

                string Aux = "";
                bool RightFound = false;
                if (_MaskToApply.StartsWith("RIGHTNUMBER("))
                {
                    RightFound = true;
                    Aux = _MaskToApply.Replace("RIGHTNUMBER(", "").Replace(")", "");
                }
                else
                {
                    Aux = _MaskToApply.Replace("LEFTNUMBER(", "").Replace(")", "");
                }
                string[] SAUX = Aux.Split('.');

                bool HasIniMoney = false;
                bool HasIniSignal = false;
                bool HasEndMoney = false;
                bool HasEndSignal = false;
                bool HasEndPercent = false;
                string partInteger = "";
                string partDecimal = "";
                int Qtd = 0;

                if (SAUX.Length != 2)
                {
                    Ok = false;
                }
                if (Ok)
                {
                    //INTEGER MASK
                    Aux = SAUX[0];
                    if (Aux.StartsWith("$") || Aux.StartsWith("S"))
                    {
                        if (Aux.StartsWith("$"))
                        {
                            HasIniMoney = true;
                        }
                        else
                        {
                            HasIniSignal = true;
                        }
                        Aux = Aux.Substring(1);
                    }
                    if (Aux.StartsWith("$") || Aux.StartsWith("S"))
                    {
                        if (Aux.StartsWith("$"))
                        {
                            HasIniMoney = true;
                        }
                        else
                        {
                            HasIniSignal = true;
                        }
                        Aux = Aux.Substring(1);
                    }
                    if (!Int32.TryParse(Aux, out Qtd))
                    {
                        Ok = false;
                    }
                    if (Ok)
                    {
                        partInteger = "";
                        for (int i = 0; i < Qtd; i++)
                        {
                            if (i % 3 == 0 && i > 0)
                            {
                                partInteger = "," + partInteger;
                            }
                            partInteger = "9" + partInteger;
                        }
                    }
                }
                //DECIMAL MASK
                if (Ok)
                {
                    Aux = SAUX[1];
                    while (Aux.EndsWith("$") || Aux.EndsWith("S") || Aux.EndsWith("%"))
                    {
                        if (Aux.EndsWith("$"))
                        {
                            HasEndMoney = true;
                        }
                        if (Aux.EndsWith("S"))
                        {
                            HasEndSignal = true;
                        }
                        if (Aux.EndsWith("%"))
                        {
                            HasEndPercent = true;
                        }
                        Aux = Aux.Substring(0, Aux.Length - 1);
                    }
                    if (!Int32.TryParse(Aux, out Qtd))
                    {
                        Ok = false;
                    }
                    if (Ok)
                    {
                        partDecimal = "";
                        for (int i = 0; i < Qtd; i++)
                        {
                            partDecimal += "9";
                        }
                    }
                }
                if (Ok)
                {
                    _MaskToApply = "";
                    if (HasIniMoney && !HasIniSignal)
                    {
                        _MaskToApply = "$*";
                    }
                    else if (!HasIniMoney && HasIniSignal)
                    {
                        _MaskToApply = "S*";
                    }
                    else if (HasIniMoney && HasIniSignal)
                    {
                        _MaskToApply = "$*S*";
                    }
                    _MaskToApply += partInteger;
                    if (partDecimal.Length > 0)
                    {
                        _MaskToApply += "." + partDecimal;
                    }
                    if (!HasEndMoney && !HasEndSignal && !HasEndPercent)
                    {
                        _MaskToApply += "*";
                    }
                    else if (!HasEndMoney && !HasEndSignal && HasEndPercent)
                    {
                        _MaskToApply += "*%*";
                    }
                    else if (!HasEndMoney && HasEndSignal && !HasEndPercent)
                    {
                        _MaskToApply += "*S*";
                    }
                    else if (!HasEndMoney && HasEndSignal && HasEndPercent)
                    {
                        _MaskToApply += "*%S*";
                    }
                    else if (HasEndMoney && !HasEndSignal && !HasEndPercent)
                    {
                        _MaskToApply += "*$*";
                    }
                    else if (HasEndMoney && !HasEndSignal && HasEndPercent)
                    {
                        _MaskToApply += "*%*$*";
                    }
                    else if (HasEndMoney && HasEndSignal && !HasEndPercent)
                    {
                        _MaskToApply += "*S*$*";
                    }
                    else if (HasEndMoney && HasEndSignal && HasEndPercent)
                    {
                        _MaskToApply += "*%S*$*";
                    }
                    if (RightFound)
                    {
                        _Rightbehavior = true;
                    }
                    if (!_MaskToApply.EndsWith("*"))
                    {
                        _MaskToApply += "*";
                    }
                }

                #endregion
                if (Ok)
                {
                    RetResolve = InputDataType.Number;
                }
            }
            else if (_MaskToApply == "SHORTDATE")
            {
                _MaskToApply = "99/99/99*";
                RetResolve = InputDataType.DateY2;
            }
            else if (_MaskToApply == "LONGDATE")
            {
                _MaskToApply = "99/99/9999*";
                RetResolve = InputDataType.DateY4;
            }
            else if (_MaskToApply == "SHORTTIME")
            {
                _MaskToApply = "99:99*";
                RetResolve = InputDataType.TimeHM;
            }
            else if (_MaskToApply == "LONGTIME")
            {
                _MaskToApply = "99:99:99*";
                RetResolve = InputDataType.TimeHMS;
            }
            else if (_MaskToApply == "SHORTTIMEAMPM")
            {
                _MaskToApply = "99:99*T";
                RetResolve = InputDataType.TimeHM;
            }
            else if (_MaskToApply == "LONGTIMEAMPM")
            {
                _MaskToApply = "99:99:99*T";
                RetResolve = InputDataType.TimeHMS;
            }
            else if (_MaskToApply.StartsWith("R{"))
            {
                bool Ok = true;
                #region transform R{P}([U|L]???) in mask

                bool UC = false;
                bool LC = false;
                int qtd = 0;

                string MK = _MaskToApply.Substring(2, 1);
                if (_ValidChar.IndexOf(MK) < 0)
                {
                    Ok = false;
                }
                if (Ok)
                {
                    _MaskToApply = _MaskToApply.Replace("R{", "");
                    _MaskToApply = _MaskToApply.Replace("}(", "");
                    _MaskToApply = _MaskToApply.Replace(")", "");
                    _MaskToApply = _MaskToApply.Substring(1);
                    if (_MaskToApply.StartsWith("U"))
                    {
                        _MaskToApply = _MaskToApply.Substring(1);
                        UC = true;
                    }
                    else if (_MaskToApply.StartsWith("L"))
                    {
                        _MaskToApply = _MaskToApply.Substring(1);
                        LC = true;
                    }
                    if (!int.TryParse(_MaskToApply, out qtd))
                    {
                        Ok = false;
                    }
                }
                if (Ok && qtd > 0)
                {
                    _MaskToApply = "";
                    for (int i = 0; i < qtd; i++)
                    {
                        _MaskToApply += MK;
                    }
                    _MaskToApply += "*";
                    if (UC)
                    {
                        _MaskToApply = "@U" + _MaskToApply;
                    }
                    else if (LC)
                    {
                        _MaskToApply = "@L" + _MaskToApply;
                    }
                }

                #endregion
                if (Ok)
                {
                    RetResolve = InputDataType.Repeater;
                }
            }
            return RetResolve;
        }

        /// <summary>
        /// Validate Content User Mask
        /// </summary>
        /// <returns>True if Valid</returns>
        private bool IsValidUserMask()
        {
            string aux = _MaskToApply.ToUpper();
            if (aux.StartsWith("@"))
            {
                aux = aux.Substring(1);
                if (!aux.StartsWith("U") && aux.StartsWith("L"))
                {
                    return false;
                }
                aux = aux.Substring(1);
            }

            char[] arr = aux.ToUpper().ToCharArray();
            bool result = true;
            bool FlagEscape = false;
            foreach (var item in arr)
            {
                if (FlagEscape)
                {
                    FlagEscape = false;
                }
                else if (item == _EscapeChar)
                {
                    FlagEscape = true;
                }
                else
                {
                    if (_ValidChar.IndexOf(item) < 0)
                    {
                        result = false;
                        break;
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// Initialize Privates controls variables reading Mask
        /// </summary>
        private void InitTextMask()
        {
            _InputToLower = false;
            _InputToUpper = false;
            _HasDecimalMask = false;
            _HasDateSepMask = false;
            _HasTimeSepMask = false;
            _ShowSignal = false;
            _ShowAMPM = false;
            _InputFirstPos = -1;
            _InputLastPos = -1;
            _ShiftLeftOnDelete = false;
            _DefaultRightCursorPos = 0;

            string aux = _MaskToApply.ToUpper();

            if (aux.StartsWith("@"))
            {
                aux = aux.Substring(1);
                if (aux.StartsWith("U"))
                {
                    _InputToUpper = true;
                }
                else if (aux.StartsWith("L"))
                {
                    _InputToLower = true;
                }
                aux = aux.Substring(1);
            }

            char[] arr = aux.ToUpper().ToCharArray();
            string result = "";
            bool FlagEscape = false;
            List<char> CMask = new List<char>();
            List<char> IMask = new List<char>();
            List<char> TMask = new List<char>();
            foreach (var item in arr)
            {
                if (FlagEscape)
                {
                    FlagEscape = false;
                    result += item.ToString();
                    CMask.Add((char)2);
                    IMask.Add((char)0);
                    TMask.Add((char)0);
                }
                else if (item == _EscapeChar)
                {
                    FlagEscape = true;
                }
                else
                {
                    if (_ValidChar.IndexOf(item) >= 0)
                    {
                        result += PromptCharacter;
                        CMask.Add((char)0);
                        IMask.Add(item);
                        TMask.Add(item);
                    }
                    else if (_ValidSignalChar.Equals(item))
                    {
                        result += CultureHelper.GetPositiveSignal(_CultureInfoDisplay).Substring(0,1);
                        CMask.Add((char)4);
                        IMask.Add((char)0);
                        TMask.Add((char)4);
                        _ShowSignal = true;
                    }
                    else if (_ValidAMPMChar.Equals(item))
                    {
                        string AMPM = CultureHelper.GetAMplaceholder(_CultureInfoDisplay);
                        result += AMPM;
                        char[] CAMPM = AMPM.ToCharArray();
                        for (int i = 0; i < CAMPM.Length; i++)
                        {
                            CMask.Add((char)4);
                            IMask.Add((char)0);
                            TMask.Add((char)4);
                        }
                        _ShowAMPM = true;
                    }
                    else if (_SpecialChar.IndexOf(item) >= 0)
                    {
                        string special = "";
                        char tchar = (char)1;
                        if (item == '/')
                        {
                            special = CultureHelper.GetDateplaceholder(_CultureInfoDisplay);
                            _HasDateSepMask = true;
                        }
                        else if (item == ':')
                        {
                            special = CultureHelper.GetTimeplaceholder(_CultureInfoDisplay);
                            _HasTimeSepMask = true;
                        }
                        else if (item == '.')
                        {
                            special = CultureHelper.GetDecimalplaceholder(_CultureInfoDisplay);
                            _HasDecimalMask = true;
                        }
                        else if (item == '%')
                        {
                            tchar = (char)5;
                            special = CultureHelper.GetPercentSymbol(_CultureInfoDisplay);
                        }
                        else if (item == '$')
                        {
                            tchar = (char)5;
                            special = CultureHelper.GetCurrencySymbol(_CultureInfoDisplay);
                        }
                        else if (item == '*')
                        {
                            tchar = (char)5;
                            special = " ";
                        }
                        else if (item == ',')
                        {
                            tchar = (char)5;
                            special = CultureHelper.GetThousandsplaceholder(_CultureInfoDisplay);
                        }
                        else
                        {
                            special = item.ToString();
                        }
                        result += special;
                        for (int i = 0; i < special.Length; i++)
                        {
                            CMask.Add(tchar);
                            IMask.Add((char)0);
                            TMask.Add(item);
                        }
                    }
                }
            }
            int pos = -1;
            foreach (var item in CMask)
            {
                pos++;
                if (item == (char)0)
                {
                    if (_InputFirstPos == -1)
                    {
                        _InputFirstPos = pos;
                    }
                    _InputLastPos = pos;
                }
            }
            //verify type mask is same in all position
            char Smask = (char)0;
            bool IsEqual = true;
            foreach (var item in IMask)
            {
                if (item != (char)0)
                {
                    if (Smask == (char)0)
                    {
                        Smask = item;
                    }
                    else
                    {
                        if (Smask != item)
                        {
                            IsEqual = false;
                            break;
                        }
                    }
                }
            }
            if (IsEqual && Smask != (char)0)
            {
                _ShiftLeftOnDelete = true;
            }
            _MaskFormated = result;
            _MaskInternalType = CMask.ToArray();
            _MaskInputChar = IMask.ToArray();
            _MaskTemplate = TMask.ToArray();
            base.MaxLength = _MaskFormated.Length;
            if (_Rightbehavior)
            {
                int? dec = GetDecimalPosition();
                if (dec.HasValue)
                {
                    if (FixedCursorRightPosition)
                    {
                        _DefaultRightCursorPos = _InputLastPos + 1;
                    }
                    else
                    {
                        _DefaultRightCursorPos = dec.Value;
                    }
                }
                else
                {
                    _DefaultRightCursorPos = _InputLastPos+1;
                }
            }
        }

        private string UnMaskText()
        {
            return UnMaskText(base.Text);
        }

        /// <summary>
        /// return Content Text widtout Mask (supress empty position)
        /// </summary>
        private string UnMaskText(string valuetext)
        {
            char[] Aux = valuetext.ToCharArray();
            StringBuilder result = new StringBuilder();
            /// char 0 = empty input position
            /// char 1 = delimit position
            /// char 2 = escape value
            /// char 3 = not empty input position
            /// char 4 = signal Position or AM/PM
            /// char 5 = Symbol Position
            bool IsNegative = false;
            bool HasValue = false;
            char DecSep = (char)0;
            CultureInfo CultCurr = null;
            if (CultureLoad == "")
            {
                CultCurr = System.Threading.Thread.CurrentThread.CurrentCulture;
            }
            else
            {
                CultCurr = _CultureInfoLoad;
            }
            for (int i = 0; i < _MaskInternalType.Length; i++)
            {
                if (i >= Aux.Length)
                {
                    break;
                }
                if (_MaskInternalType[i] == (char)0)
                {
                    if (ReplaceEmptyNumeric != "" && _MaskFormated.Substring(i,1) == "9")
                    {
                        result.Append(ReplaceEmptyNumeric);
                    }
                    if (ReplaceEmptyText != "" && _MaskFormated.Substring(i, 1) == "X")
                    {
                        result.Append(ReplaceEmptyText);
                    }
                }
                else if (_MaskInternalType[i] == (char)1)
                {
                    ///  / = Date placeholder
                    ///  : = Time placeholder
                    ///  . = Decimal placeholder
                    if (UnMaskPreserveDisplayCulture)
                    {
                        if (Aux[i].ToString() == CultureHelper.GetDecimalplaceholder(_CultureInfoDisplay))
                        {
                            DecSep = Aux[i];
                        }
                        result.Append(Aux[i]);
                    }
                    else
                    {
                        if (Aux[i].ToString() == CultureHelper.GetDecimalplaceholder(_CultureInfoDisplay))
                        {
                            DecSep = CultureHelper.GetDecimalplaceholder(CultCurr).ToCharArray()[0];
                            result.Append(DecSep);
                        }
                        else if (Aux[i].ToString() == CultureHelper.GetDateplaceholder(_CultureInfoDisplay))
                        {
                            result.Append(CultureHelper.GetDateplaceholder(CultCurr));
                        }
                        else if (Aux[i].ToString() == CultureHelper.GetTimeplaceholder(_CultureInfoDisplay))
                        {
                            result.Append(CultureHelper.GetTimeplaceholder(CultCurr));
                        }
                    }
                }
                else if (_MaskInternalType[i] == (char)3) // input user
                {
                    result.Append(Aux[i]);
                    HasValue = true;
                }
                else if (_MaskInternalType[i] == (char)4) // signal or AM/PM
                {
                    if (UnMaskPreserveDisplayCulture)
                    {
                        if (_ShowSignal)
                        {
                            if (Aux[i].ToString() == CultureHelper.GetNegativeSignal(_CultureInfoDisplay))
                            {
                                if (!IsNegative)
                                {
                                    IsNegative = true;
                                }
                            }
                        }
                        else if (_ShowAMPM)
                        {
                            result.Append(Aux[i]);
                        }
                    }
                    else
                    {
                        if (_ShowSignal)
                        {
                            if (Aux[i].ToString() == CultureHelper.GetNegativeSignal(CultCurr))
                            {
                                if (!IsNegative)
                                {
                                    IsNegative = true;
                                }
                            }
                        }
                        else if (_ShowAMPM)
                        {
                            result.Append(Aux[i]);
                        }
                    }
                }
            }
            if (!HasValue)
            {
                result.Remove(0, result.Length);
            }
            else
            {
                if (result[result.Length - 1] == DecSep)
                {
                    result.Remove(result.Length - 1, 1);
                }
                if (result[0] == DecSep)
                {
                    result.Insert(0, new char[] { '0' });
                }
                if (IsNegative)
                {
                    if (UnMaskPreserveDisplayCulture)
                    {
                        result.Insert(0, CultureHelper.GetNegativeSignal(_CultureInfoDisplay).ToCharArray());
                    }
                    else
                    {
                        result.Insert(0, CultureHelper.GetNegativeSignal(CultCurr).ToCharArray());
                    }
                }
            }
            return result.ToString();
        }

        #endregion

        #region Public Dependency Properties

        /// <summary>
        /// Content Mask for input
        /// </summary>
        public string Mask
        {
            //TODO RESET MASK AND INITIALIZE WHEN CHANGE AT RUNTIME
            get { return (string)GetValue(MaskProperty); }
            set {
                SetValue(MaskProperty, value);
                if (Common.IsInDesignMode)
                {
                    ResolvePartternMask();
                    SetValue(TextProperty, _MaskToApply);
                }
            }
        }

        public static readonly DependencyProperty MaskProperty =
            DependencyProperty.Register("Mask", typeof(string), typeof(MaskedEdit), new PropertyMetadata(""));

        /// <summary>
        /// Prompt Char 
        /// </summary>
        public string PromptCharacter
        {
            get
            {
                char value = (char)GetValue(PromptCharacterProperty);
                if (value.Equals((char)0))
                {
                    return "";
                }
                return value.ToString();
            }
            set
            {
                char[] cvalue = value.ToCharArray();
                if (string.IsNullOrEmpty(value))
                {
                    cvalue = new char[] { '0' };
                }
                SetValue(PromptCharacterProperty, cvalue[0]);
            }
        }

        public static readonly DependencyProperty PromptCharacterProperty =
            DependencyProperty.Register("PromptCharacter", typeof(char), typeof(MaskedEdit), new PropertyMetadata('_'));

        /// <summary>
        /// Culture code  for Input data
        /// </summary>
        public string CultureInput
        {
            get { return (string)GetValue(CultureInputProperty); }
            set { SetValue(CultureInputProperty, value); }
        }

        public static readonly DependencyProperty CultureInputProperty =
            DependencyProperty.Register("CultureInput", typeof(string), typeof(MaskedEdit), new PropertyMetadata("", CultureInputPropertyCallBack));

        /// <summary>
        /// Culture code for Load data
        /// </summary>
        public string CultureLoad
        {
            get { return (string)GetValue(CultureLoadProperty); }
            set { SetValue(CultureLoadProperty, value); }
        }

        public static readonly DependencyProperty CultureLoadProperty =
            DependencyProperty.Register("CultureLoad", typeof(string), typeof(MaskedEdit), new PropertyMetadata("", CultureLoadPropertyCallBack));

        /// <summary>
        /// Custom string Filter 
        /// </summary>
        public string FilterText
        {
            get { return (string)GetValue(FilterTextProperty); }
            set { SetValue(FilterTextProperty, value); }
        }

        public static readonly DependencyProperty FilterTextProperty =
            DependencyProperty.Register("FilterText", typeof(string), typeof(MaskedEdit), new PropertyMetadata(""));

        /// <summary>
        /// Negative Background Color
        /// </summary>
        public Brush NegativeBackground
        {
            get { return (Brush)GetValue(NegativeBackgroundProperty); }
            set { SetValue(NegativeBackgroundProperty, value); }
        }

        public static readonly DependencyProperty NegativeBackgroundProperty =
            DependencyProperty.Register("NegativeBackground", typeof(Brush), typeof(MaskedEdit), new PropertyMetadata(null));

        /// <summary>
        /// Negative Foreground Color
        /// </summary>
        public Brush NegativeForeground
        {   
            get { return (Brush)GetValue(NegativeForegroundProperty); }
            set { SetValue(NegativeForegroundProperty, value); }
        }

        public static readonly DependencyProperty NegativeForegroundProperty =
            DependencyProperty.Register("NegativeForeground", typeof(Brush), typeof(MaskedEdit), new PropertyMetadata(null));

        /// <summary>
        /// Preserve delimite in Date/Time/Number to  en-US Culture
        /// </summary>
        public bool UnMaskPreserveDisplayCulture
        {
            get { return (bool)GetValue(UnMaskPreserveDisplayCultureProperty); }
            set { SetValue(UnMaskPreserveDisplayCultureProperty, value); }
        }

        public static readonly DependencyProperty UnMaskPreserveDisplayCultureProperty =
            DependencyProperty.Register("UnMaskPreserveDisplayCulture", typeof(bool), typeof(MaskedEdit), new PropertyMetadata(false));


        /// <summary>
        /// Text with unmask value
        /// </summary>
        public string TextUnMasked
        {
            get 
            {
                return UnMaskText();
            }
        }

        public bool UnMaskedAtLostfocus
        {
            get { return (bool)GetValue(UnMaskedAtLostfocusProperty); }
            set { SetValue(UnMaskedAtLostfocusProperty, value); }
        }

        public static readonly DependencyProperty UnMaskedAtLostfocusProperty =
            DependencyProperty.Register("UnMaskedAtLostfocus", typeof(bool), typeof(MaskedEdit), new PropertyMetadata(false));

        public bool FixedCursorRightPosition
        {
            get { return (bool)GetValue(FixedCursorRightPositionProperty); }
            set { SetValue(FixedCursorRightPositionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for FixedCursorRightPosition.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty FixedCursorRightPositionProperty =
            DependencyProperty.Register("FixedCursorRightPosition", typeof(bool), typeof(MaskedEdit), new PropertyMetadata(false));

        public string ReplaceEmptyText
        {
            get {
                char value = (char)GetValue(ReplaceEmptyTextProperty);
                if (value.Equals((char)0))
                {
                    return "";
                }
                return value.ToString();
            }
            set 
            {
                char[] cvalue = value.ToCharArray();
                if (string.IsNullOrEmpty(value))
                {
                    cvalue = new char[] { '0' };
                }
                SetValue(ReplaceEmptyTextProperty, cvalue[0]); 
            }
        }

        public static readonly DependencyProperty ReplaceEmptyTextProperty =
            DependencyProperty.Register("ReplaceEmptyText", typeof(char), typeof(MaskedEdit), new PropertyMetadata((char)0));

        public string ReplaceEmptyNumeric
        {
            get {
                char value = (char)GetValue(ReplaceEmptyNumericProperty);
                if (value.Equals((char)0))
                {
                    return "";
                }
                return value.ToString();
            }
            set 
            {
                char[] cvalue = value.ToCharArray();
                if (string.IsNullOrEmpty(value))
                {
                    cvalue = new char[] { '0' };
                }
                SetValue(ReplaceEmptyNumericProperty, cvalue[0]); 
            }
        }

        public static readonly DependencyProperty ReplaceEmptyNumericProperty =
            DependencyProperty.Register("ReplaceEmptyNumeric", typeof(char), typeof(MaskedEdit), new PropertyMetadata((char)0));

        
        #endregion

        #region Private Dependency Properties
        private static void CultureInputPropertyCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            try
            {
                new CultureInfo((string)e.NewValue);
            }
            catch
            {
                throw new Exception(String.Format(Resource.MaskEdit_CultureInputInvalid,e.NewValue));
            }
        }

        private static void CultureLoadPropertyCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            try
            {
                new CultureInfo((string)e.NewValue);
            }
            catch
            {
                throw new Exception(String.Format(Resource.MaskEdit_CultureLoadInvalid, e.NewValue));
            }
        }

        #endregion
    }
}
